package com.probos.bosnatuur.monitor;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
// import org.xml.sax.InputSource;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class ProjectMap extends MapActivity  {
	private BosNatuurMapView mapView;
	
//	<Point>
//		<coordinates>-122.0841430, 37.4219720, 0</coordinates>
//	</Point> 

	// Minimum & maximum latitude so we can span it
	// The latitude is clamped between -80 degrees and +80 degrees inclusive
	// thus we ensure that we go beyond that number
	private int minLatitude = (int)(+81 * 1E6);
	private int maxLatitude = (int)(-81 * 1E6);
	
	// Minimum & maximum longitude so we can span it
	// The longitude is clamped between -180 degrees and +180 degrees inclusive
	// thus we ensure that we go beyond that number
	private int minLongitude  = (int)(+181 * 1E6);
	private int maxLongitude  = (int)(-181 * 1E6);

	public static final String KML_PLACEMARK = "Placemark";
	public static final String KML_NAME = "name";	
	public static final String KML_DESCRIPTION = "description";
	public static final String KML_POINT = "Point";
	public static final String KML_COORDINATES = "coordinates";
	
	private static final int MENU_LIST = Menu.FIRST;
	private static final int MENU_MAP = Menu.FIRST+1;
	private static final int MENU_SAT = Menu.FIRST+2;	

	private static final int GROUP_MAP = Menu.FIRST;

    private ProjectDbAdapter mDbHelper;
    private long mProjectId;
    private String mTitle;
    private Context mCtx;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCtx = this;

        setContentView(R.layout.project_map);
        
        mapView = (BosNatuurMapView)findViewById(R.id.mapview);
        
        mapView.setOnLongpressListener(new BosNatuurMapView.OnLongpressListener() {
			public void onLongpress(MapView view, final GeoPoint longpressLocation) {
				// TODO Auto-generated method stub
	            runOnUiThread(new Runnable() {
		            public void run() {
		                // Insert your longpress action here
		            	Toast.makeText(mCtx, "lat:"+longpressLocation.getLatitudeE6(), Toast.LENGTH_SHORT).show();
		            }
	            });
			}
        });

        Bundle extras = getIntent().getExtras();
    	mProjectId = (long) 0;  
	    
	    if (extras != null) {
	    	mProjectId = extras.getLong(ProjectDbAdapter.KEY_ROWID);
	    	mTitle = extras.getString(ProjectDbAdapter.KEY_TITLE);
	    	setTitle(mTitle);	    	
	    }
	    
        Drawable target = this.getResources().getDrawable(R.drawable.target);
        
        BosNatuurOverlay overlay = new BosNatuurOverlay(target,this);

        TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(','); 

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();               
        DocumentBuilder builder = null;        
		try {
			builder = factory.newDocumentBuilder();
		} catch (ParserConfigurationException e1) {
			e1.printStackTrace();
		}
 
        mDbHelper = new ProjectDbAdapter(this);
        mDbHelper.open();
 		
        // Get all of the rows from the database and create the item list
    	Cursor elementsCursor = mDbHelper.fetchAllElements(mProjectId);
        // startManagingCursor(elementsCursor);
        int max_nr = 0;
        
        Paint white = new Paint();
        white.setColor(Color.WHITE);
        white.setTextSize(12);
        
        Paint black = new Paint();
        black.setStyle(Style.STROKE);
    	
        if ((elementsCursor != null) && (builder != null)) {
        	while(elementsCursor.moveToNext()) {
        		Long id = elementsCursor.getLong(elementsCursor.getColumnIndex(ProjectDbAdapter.KEY_ROWID));
        		String strName = elementsCursor.getString(elementsCursor.getColumnIndex(ProjectDbAdapter.KEY_TITLE));
        		String strShape = elementsCursor.getString(elementsCursor.getColumnIndex(ProjectDbAdapter.KEY_SHAPE));
        		String strDescription = elementsCursor.getString(elementsCursor.getColumnIndex(ProjectDbAdapter.KEY_DESCRIPTION));
        		String hoofdcat = elementsCursor.getString(elementsCursor.getColumnIndex("hoofdcat"));
        		String ds = elementsCursor.getString(elementsCursor.getColumnIndex("datum"));
        		
        		Integer nr = elementsCursor.getInt(elementsCursor.getColumnIndex("nr"));

	        	int kleur = Color.GRAY;
	        					
	        	// index 5 = "hoofd"
				int hoofd_index = elementsCursor.getColumnIndex("hoofd");
	        	if (!elementsCursor.isNull(hoofd_index)) {
		        	Integer position = elementsCursor.getInt(hoofd_index);
		        	
		        	if (position > 0) {
						int colorPos = (position-1) % ProjectElements.colors.length;
						
						int clr = ProjectElements.colors[colorPos];
						
						int R = clr % 256;
						int G = (clr / 256 ) % 256;
						int B = (clr / 256 / 256 ) % 256;
								  
						kleur = Color.argb(255, R, G, B);
		        	}
		        }
        		
        		int i = -1;
        		ArrayList<String> parts = new  ArrayList<String>();
        		i = elementsCursor.getColumnIndex("hoofdcat");
        		if (i >= 0 && !elementsCursor.isNull(i)){
        			parts.add(elementsCursor.getString(i));
        		}
        		i = elementsCursor.getColumnIndex("datum");
        		if (i >= 0 && !elementsCursor.isNull(i)){
        			Date d = mDbHelper.DBStringToDate(elementsCursor.getString(i));
        			parts.add(mDbHelper.DateToString(d) + " " + mDbHelper.TimeToString(d));
        		}
        		i = elementsCursor.getColumnIndex(ProjectDbAdapter.KEY_DESCRIPTION);
        		if (i >= 0 && !elementsCursor.isNull(i)){
        			parts.add(elementsCursor.getString(i));
        		}
   				String snippet = TextUtils.join("\n", parts); 
/*
        		if (elementsCursor.isNull(elementsCursor.getColumnIndex("nr"))) {
        			max_nr++;
        			ContentValues values = new ContentValues();
        			values.put("nr", max_nr);
        			mDbHelper.updateElementValues(id, values);        			
        		} else {
        			int nr = elementsCursor.getInt(elementsCursor.getColumnIndex("nr"));
        			if (nr > max_nr) max_nr = nr;
        		}
        		
    			ContentValues values = new ContentValues();
    			values.put("element_seq", max_nr);
    			mDbHelper.updateProjectValues(mProjectId, values);        			
 */      		
				try {
					JSONArray a = new JSONArray(strShape);
        	        for (i=0;i<a.length();i++) {
        	        	JSONObject json = a.getJSONObject(i);
                        GeoPoint point = JSONToGeoPoint(json);
                        BosNatuurOverlayItem item = new BosNatuurOverlayItem(point, strName, snippet, id, kleur, (int) nr);
                        
//                        ShapeDrawable marker = new ShapeDrawable( new  OvalShape() );
//                        marker.setIntrinsicHeight(10);
//                        marker.setIntrinsicWidth(10);
//                        marker.getPaint().setColor(kleur);

//                        Bitmap bitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_8888); 
//                        Canvas canvas = new Canvas(bitmap); 

//                        marker.setBounds(0, 0, 10, 10); 
//                        marker.draw(canvas);
//                        
//                        canvas.drawText(id.toString(), 8, 16, white);
//                        canvas.drawCircle(10, 10, 10, black);
//                        
//                        Bitmap bm2 = Bitmap.createScaledBitmap(bitmap, 10, 10, false);
//                        
//                        BitmapDrawable bm = new BitmapDrawable(getResources(),bm2);
                        
                        // Log.i("BosNatuurMonitor.ProjectMap.JSONToGeoPoint",point.toString());
//                        overlay.addItem(item, marker);
                        overlay.addItem(item);
        	        }		        			
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					Log.e("BosNatuurMonitor.ProjectMap.JSONArray",e.getMessage()+ "\n" + strShape);
				}
        	}
        }
        
        elementsCursor.deactivate();
        mDbHelper.close();
        
        MapView mapView = (MapView) findViewById(R.id.mapview);
        mapView.setBuiltInZoomControls(true);        
        List<Overlay> mapOverlays = mapView.getOverlays();
        mapOverlays.add(overlay);
        
        MapController mc = mapView.getController();
        
        // List<Point> mPoints = new ArrayList<Point>();
        
		for (int i=0;i<overlay.size();i++) {

			GeoPoint p = overlay.getItem(i).getPoint();
			
			int latitude = p.getLatitudeE6();
			int longitude = p.getLongitudeE6();
			
			// Sometimes the longitude or latitude gathering
			// did not work so skipping the point
			// doubt anybody would be at 0 0
			if (latitude != 0 && longitude !=0)  {
				
				// Sets the minimum and maximum latitude so we can span and zoom
				minLatitude = (minLatitude > latitude) ? latitude : minLatitude;
				maxLatitude = (maxLatitude < latitude) ? latitude : maxLatitude;		
				
				// Sets the minimum and maximum latitude so we can span and zoom
				minLongitude = (minLongitude > longitude) ? longitude : minLongitude;
				maxLongitude = (maxLongitude < longitude) ? longitude : maxLongitude;
				
				// mPoints.add(new Point(latitude, longitude));
			}
		}        
        
        if (overlay.size() > 0) {
    		// Zoom to span from the list of points
    		mc.zoomToSpan(
    				(maxLatitude - minLatitude), 
    				(maxLongitude - minLongitude));
    		
    		// Animate to the center cluster of points
    		mc.animateTo(new GeoPoint(
    				 (maxLatitude + minLatitude)/2,
    				 (maxLongitude + minLongitude)/2 ));
        	        	
            mapView.invalidate();   	
        }
        
/*	    Button clickBtn = (Button) findViewById(R.id.clickBtn);
        clickBtn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
            	MapView mapView = (MapView) findViewById(R.id.mapview);
            	mapView.setSatellite(!mapView.isSatellite());            	
        	}
        });*/
    }

    @Override
	protected boolean isRouteDisplayed() {
		return false;
	}

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	boolean result = super.onCreateOptionsMenu(menu);
    	
    	MenuItem menu_test = menu.add(0, MENU_LIST, 0, R.string.map_menu_list);
    	
    	SubMenu menu_sub = menu.addSubMenu(R.string.map_menu_view);

    	MenuItem menu_map = menu_sub.add(GROUP_MAP, MENU_MAP, 0, R.string.map_menu_map);
    	MenuItem menu_sat = menu_sub.add(GROUP_MAP, MENU_SAT, 0, R.string.map_menu_sat);
        	
    	menu_sub.setGroupCheckable(GROUP_MAP, true, true);
    	
    	MapView mapView = (MapView) findViewById(R.id.mapview);
    	if (mapView.isSatellite()) {
    		menu_sat.setChecked(true);
    	} else {
    		menu_map.setChecked(true);
    	}
   	
    	return result;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	MapView mapView = (MapView) findViewById(R.id.mapview);    	
    	switch (item.getItemId()) {
    	case MENU_LIST:
            Intent i = new Intent(this, ProjectElements.class);            
            i.putExtra(ProjectDbAdapter.KEY_ROWID, mProjectId);
            i.putExtra(ProjectDbAdapter.KEY_TITLE, mTitle);
            startActivity(i);
            
    		SharedPreferences settings = getSharedPreferences(BosNatuurMonitor.PREFS_NAME, 0);     		
    		SharedPreferences.Editor editor = settings.edit();
			editor.putInt("current_view", BosNatuurMonitor.VIEW_LIST); 
			editor.commit();

        	setResult(RESULT_CANCELED);
            finish();
    	case MENU_MAP:
        	mapView.setSatellite(false);
        	item.setChecked(true);
    		return true;
		case MENU_SAT:
	    	mapView.setSatellite(true);
	    	item.setChecked(true);
			return true;
		}
    	return super.onOptionsItemSelected(item);
    }
    
    public void updateItem(BosNatuurOverlayItem item) {
        mDbHelper = new ProjectDbAdapter(this);
        mDbHelper.open();
        
        ContentValues values = new ContentValues();
        Double lon = ((double) item.getPoint().getLongitudeE6())/1000000;
        Double lat = ((double) item.getPoint().getLatitudeE6())/1000000;
        
        String strLocation = "<Point><coordinates>" + lon + "," + lat + "</coordinates></Point>";

        JSONArray a = new JSONArray();
        a.put(GeoPointToJSON(item.getPoint()));
        strLocation = a.toString();

        values.put(ProjectDbAdapter.KEY_SHAPE, strLocation);
        
        mDbHelper.updateElementValues(item.getID(), values);
        
        mDbHelper.close();
    }
    
    public static JSONObject GeoPointToJSON(GeoPoint p) {
    	JSONObject json = new JSONObject();
    	try {
			json.put("lat", ((double) p.getLatitudeE6())/1000000);
	    	json.put("lon", ((double) p.getLongitudeE6())/1000000);
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return json;
    }
    
    public static GeoPoint JSONToGeoPoint(JSONObject json) {
  
        double lat=0;
        double lon=0;
        
		try {
			lat = json.getDouble("lat");
	        lon = json.getDouble("lon");
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

    	return new GeoPoint((int) (lat*1000000), (int) (lon*1000000));
    }
}
